module Article exposing (..)
import Html exposing (Html, a, button, code, div, h1, li, text, ul,h2,br,textarea,input,span)
import Html.Attributes exposing (value,style)
import Html.Events exposing (onClick,onInput)
import Http
import Json.Decode as Decode
import Json.Encode as Encode
import Navigation
import Utils

type Msg 
 = GetArticleResult (Result Http.Error (Result String Article))
 | ConfirmUpdate
 | UpdateResult (Result Http.Error (Result String String))
 | InputTitle String
 | InputContent String
 | ConfirmDel
 | Delete
 | CancelDel
 | DelResult (Result Http.Error (Result String String))

type Model = Model Id Article Log Delable

type Article = Article Id Title Content UpdateTime

initModel : Model
initModel = Model -1 (Article -1 "" "" "") "" False

type alias Id = Int
type alias Log = String
type alias Title = String
type alias Content = String
type alias UpdateTime = String
type alias Delable = Bool

cmdGetArticle : Id -> Cmd Msg
cmdGetArticle id =
 let 
  url = "/article/" ++ toString id
  okDecoder = Decode.field "ok" (Decode.map Ok (Decode.map4 Article (Decode.field "id" Decode.int) (Decode.field "title" Decode.string) (Decode.field "content" Decode.string) (Decode.field "update_time" Decode.string)))
  errDecoder = Decode.field "err" (Decode.map Err Decode.string)
  decoder = Decode.oneOf [okDecoder,errDecoder]
  request = Http.get url decoder
 in 
  Http.send GetArticleResult request

cmdUpdateArticle : Id -> Article -> Cmd Msg
cmdUpdateArticle id (Article aid title content time) =
 let 
  url = "/article/" ++ toString id
  body = Http.jsonBody (Encode.object [("title",Encode.string title),("content",Encode.string content),("update_time",Encode.string time)])
  decoder = Decode.oneOf [Decode.map Ok (Decode.field "ok" Decode.string),Decode.map Err (Decode.field "err" Decode.string)]
  request = Utils.put url body decoder
 in Http.send UpdateResult request
 

refresh : Id -> Model -> (Model,Cmd Msg)
refresh nodeId (Model id article log delable) = (Model nodeId article "" delable,cmdGetArticle nodeId)

reset : Id -> Model -> Model
reset id (Model oldId article log delable) = (Model id article log delable)
 

cmdDelArticle : Id  -> Cmd Msg
cmdDelArticle articleId =
 let 
  url = "/article/" ++ toString articleId
  decoder = Decode.oneOf [Decode.map Ok (Decode.field "ok" Decode.string),Decode.map Err (Decode.field "err" Decode.string)]
  request = Utils.del url decoder
 in Http.send DelResult request


update : Msg -> Model -> (Model,Cmd Msg)
update msg ((Model id ((Article aid title content time) as article) log delable) as model) = 
 case msg of
  GetArticleResult res ->
   case res of
    Err err -> (Model id article (log ++ "  服务器响应失败: " ++ (toString err)) delable,Cmd.none)
    Ok res ->
     case res of
      Err err -> (Model id article (log ++ "  获取文章失败: " ++ (toString err)) delable,Cmd.none)
      Ok newArticle -> (Model id newArticle (log ++ "  响应成功") delable,Cmd.none)

  ConfirmUpdate ->
   (Model id article (log ++ "  确认更新文章 " ) delable,cmdUpdateArticle id article)

  ConfirmDel -> 
   (Model id article (log ++ "  确认删除文章 " ) delable,cmdDelArticle aid)

  DelResult (Err err) -> (Model id article (log ++ "  服务器响应出错: " ++ (toString err) ) delable,Cmd.none)
  DelResult (Ok ok) -> 
   case ok of
    Err err -> (Model id article (log ++ "  删除文章失败: " ++ err ) delable,Cmd.none)
    Ok ok -> (Model id article (log ++ "  删除文章成功 " ) delable,Navigation.back 1)  

  UpdateResult (Err err) -> (Model id article (log ++ "  服务器响应出错: " ++ (toString err) ) delable,Cmd.none)
  UpdateResult (Ok ok) -> 
   case ok of
    Err err -> (Model id article (log ++ "  更新文章失败: " ++ err ) delable,Cmd.none)
    Ok ok -> (Model id article (log ++ "  更新文章成功 " ) delable,Cmd.none)

  InputTitle str -> (Model id (Article aid str content time) log delable,Cmd.none)
  InputContent str -> (Model id (Article aid title str time) log delable,Cmd.none)

  CancelDel -> (Model id article log False,Cmd.none)
  Delete -> (Model id article log True,Cmd.none)


view : Model -> Html Msg
view (Model id ((Article aid title content time) as article) log delable) =
 let 
  delView = 
   case delable of
    True -> 
     span [] 
      [ button [style [("background-color","red"),("color","white")],onClick ConfirmDel] [text "Confirm"]
      , button [style [("background-color","green"),("color","white")],onClick CancelDel] [text "Cancel" ] ]
    False -> button [style [("background-color","red"),("color","white")],onClick Delete] [text "Delete"]
   
 in 
  div []
   [ h2 [] [text ("Article id: " ++ toString aid)]
   , div [] [articleView article]
   , div [] 
      [ button [onClick ConfirmUpdate] [text "Update"]
      , delView ]
   , br [] [], text ("Article: " ++ log) ]


articleView : Article -> Html Msg
articleView (Article aid title content updateTime) = 
  div []
   [ div [] [text "标题: ",input [onInput InputTitle,value title] []]
   , div [] [text ("update time: " ++ updateTime)]
   , textarea [style [("width","100%"),("height","50vh")],onInput InputContent] [text content]
   , br [] [] ]
 